<<<<<<< HEAD
package main
=======
package instagram
>>>>>>> e9f25868439de4d40b5074e80fa41a0447039998

import (
	"log"
	"io/ioutil"
	"regexp"
	"strings"
	"encoding/json"
	"os"
	"io"
	"bytes"
	"fmt"
	"github.com/nofuck/instagram/httptool"
)

const Proxy = "http://127.0.0.1:19999"

type SharedData struct {
	EntryData EntryData `json:"entry_data"`
}

type EntryData struct {
	PostPage []Post `json:"PostPage"`
}

type Post struct {
	Graphql Graphql `json:"graphql"`
}

type Graphql struct {
	ShortcodeMedia Media `json:"shortcode_media"`
}

type Media struct {
	Id                    string                `json:"id"`
	Shortcode             string                `json:"shortcode"`
	Dimensions            Dimensions            `json:"dimensions"`
	DisplayUrl            string                `json:"display_url"`
	DisplayResources      []DisplayResource     `json:"display_resources"`
	IsVideo               bool                  `json:"is_video"`
	Owner                 Owner                 `json:"owner"`
	EdgeSidecarToChildren EdgeSidecarToChildren `json:"edge_sidecar_to_children"`
}

type Dimensions struct {
	Height int `json:"height"`
	Width  int `json:"width"`
}

type DisplayResource struct {
	Src          string `json:"src"`
	ConfigWidth  int    `json:"config_width"`
	ConfigHeight int    `json:"config_height"`
}

type Owner struct {
	Id                string `json:"id"`
	ProfilePicUrl     string `json:"profile_pic_url"`
	Username          string `json:"username"`
	BlockedByViewer   bool   `json:"blocked_by_viewer"`
	FollowedByViewer  bool   `json:"followed_by_viewer"`
	FullName          string `json:"full_name"`
	HasBlockedViewer  bool   `json:"has_blocked_viewer"`
	IsPrivate         bool   `json:"is_private"`
	IsUnpublished     bool   `json:"is_unpublished"`
	IsVerified        bool   `json:"is_verified"`
	RequestedByViewer bool   `json:"requested_by_viewer"`
}

type EdgeSidecarToChildren struct {
	Edges []Edge `json:"edges"`
}

type Edge struct {
	Node Media `json:"node"`
}

type InsError struct {
	Msg string
}

func (err *InsError) Error() string {
	return err.Msg
}

func regexpData(insHtml []byte) string {
	expr := "<script type=\"text/javascript\">window._sharedData = (?P<nnn>.*)</script>"
	rege := regexp.MustCompile(expr)
	str := rege.FindSubmatch(insHtml)
	json := strings.TrimRight(strings.TrimSpace(string(str[1])), ";")
	return json
}

func GetImage(postUrl string) *SharedData {
	response, err := httptool.HttpProxyGet(postUrl)
	if err != nil {
		log.Fatal(err)
	}
	if response.StatusCode != 200 {
		log.Fatal(err)
	}
	body, err := ioutil.ReadAll(response.Body);
	if err != nil {
		log.Fatal(err)
	}

	jsonHtml := regexpData(body)
	sharedData := &SharedData{}
	json.Unmarshal([]byte(jsonHtml), sharedData)
	return sharedData
}

func GetImageUrl(data *SharedData) ([]string, error) {
	if postData := data.EntryData.PostPage; postData != nil {
		urls := make([]string, 0)
		firstIndex := postData[0]
		media := firstIndex.Graphql.ShortcodeMedia

		edges := media.EdgeSidecarToChildren.Edges
		if edges != nil {
			for _, edge := range edges {
				urls = append(urls, edge.Node.DisplayUrl)
			}
		} else {
			urls = append(urls, media.DisplayUrl)
		}
		return urls, nil
	}
	return nil, &InsError{"Post data is empty"}
}

func SaveImage(imageUrl string, downloadPath string) bool {
	reg, _ := regexp.Compile(`(\w|\d|_)*.jpg`)
	imageName := reg.FindStringSubmatch(imageUrl)[0]

	response, err := httptool.HttpProxyGet(imageUrl);
	if err != nil {
		fmt.Println(err)
		return false
	}

	body, _ := ioutil.ReadAll(response.Body)
	defer response.Body.Close()

	f, _ := os.Create(downloadPath + imageName)
	io.Copy(f, bytes.NewReader(body))
	return true
}
